package cmd

import (
	"context"
	"github.com/emicklei/go-restful"
	urlruntime "k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/client-go/kubernetes"
	"k8s.io/klog"
	"metabank/api"
	"metabank/cache"
	"metabank/conf"
	"metabank/informers"
	"net/http"
)

type APIServer struct {
	Server *http.Server

	Config *conf.Config

	// webservice container, where all webservice defines
	container *restful.Container

	K8sClient *kubernetes.Clientset
	McpClient *kubernetes.Clientset

	SyncInformer cache.InformersOptions
	Caches       map[string]map[string]string

	InformerFactory informers.InformerFactory
}

func (s *APIServer) PrepareRun() error {
	s.container = restful.NewContainer()
	s.container.Router(restful.CurlyRouter{})
	s.initAPIs()
	s.Server.Handler = s.container
	return nil
}

func (s *APIServer) initAPIs() {
	urlruntime.Must(api.AddToContainer(s.container, s.Caches))
}

func (s *APIServer) Run(ctx context.Context) error {

	err := s.waitForCacheSync(s.InformerFactory.KubernetesSharedInformerFactory(), ctx.Done())
	if err != nil {
		return err
	}

	err = s.SyncInformer.SyncConfigMap()
	if err != nil {
		return err
	}

	shutdownCtx, cancel := context.WithCancel(context.Background())
	defer cancel()
	go func() {
		<-ctx.Done()
		_ = s.Server.Shutdown(shutdownCtx)
	}()

	klog.V(0).Infof("Start listening on %s", s.Server.Addr)
	if s.Server.TLSConfig != nil {

		err = s.Server.ListenAndServeTLS("", "")
	} else {
		err = s.Server.ListenAndServe()
	}

	return err
}

func (s *APIServer) waitForCacheSync(sharedInformerFactory informers.GenericInformerFactory, stopCh <-chan struct{}) error {
	sharedInformerFactory.Start(stopCh)
	sharedInformerFactory.WaitForCacheSync(stopCh)
	return nil
}
